#include "mainwindow.h"

#include <QAction>
#include <QDir>
#include <QDirModel>
#include <QFileInfo>
#include <QInputDialog>
#include <QLabel>
#include <QListWidget>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QPixmap>
#include <QToolBar>
#include <QTreeView>
#include <QTreeWidget>
#include <QtDBus>

#include <iostream>
#include <string>

using std::cout;
using std::cerr;
using std::endl;
using std::string;

namespace TuboxUi {

MainWindow::MainWindow(const QString &path) : path(path), QMainWindow(0) {
	//Central Widget
	tree = new QTreeView(this);
	updateList();

	updates = new QListWidget(this);

	//Actions
	QAction *copyAction = new QAction(QIcon(QPixmap("img/edit-copy.png")), tr("&Copy"), this);
	QAction *moveAction = new QAction(QIcon(QPixmap("img/revert.png")), tr("&Move"), this);
	QAction *removeAction = new QAction(QIcon(QPixmap("img/edit-delete.png")), tr("&Remove"), this);
	QAction *renameAction = new QAction(QIcon(QPixmap("img/edit-rename.png")), tr("&Rename"), this);
	QAction *createFolderAction = new QAction(QIcon(QPixmap("img/folder-new.png")), tr("Create &Folder"), this);
//	QAction *configAction = new QAction(QIcon(QPixmap("img/configure.png")), tr("C&onfigurations"), this);
	QAction *exitAction = new QAction(QIcon(QPixmap("img/application-exit.png")), tr("&Exit"), this);
	QAction *aboutAction = new QAction(QIcon(QPixmap("img/help-about.png")), tr("&About"), this);

	connect(copyAction, SIGNAL(triggered()), this, SLOT(copy()));
	connect(moveAction, SIGNAL(triggered()), this, SLOT(move()));
	connect(removeAction, SIGNAL(triggered()), this, SLOT(remove()));
	connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
	connect(createFolderAction, SIGNAL(triggered()), this, SLOT(createFolder()));
	//TODO connect about
	connect(exitAction, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit()));
	connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(disconnect()));

	//Menus
	QMenu *fileMenu = new QMenu(tr("&File"), this);

	fileMenu->addAction(copyAction);
	fileMenu->addAction(moveAction);
	fileMenu->addAction(removeAction);
	fileMenu->addAction(renameAction);
	fileMenu->addAction(createFolderAction);
//	fileMenu->addSeparator();
//	fileMenu->addAction(configAction);
	fileMenu->addSeparator();
	fileMenu->addAction(exitAction);

	QMenu *helpMenu = new QMenu(tr("&Help"), this);

	helpMenu->addAction(aboutAction);

	//Toolbar
	QToolBar *toolBar = new QToolBar(this);
	toolBar->setAllowedAreas(Qt::BottomToolBarArea);
	toolBar->setFloatable(false);
	toolBar->setOrientation(Qt::Horizontal);
	toolBar->setMovable(false);

	toolBar->addAction(copyAction);
	toolBar->addAction(moveAction);
	toolBar->addAction(removeAction);
	toolBar->addAction(renameAction);
	toolBar->addAction(createFolderAction);

	//Tabwidget
	QTabWidget *tabsWidget = new QTabWidget(this);
	tabsWidget->addTab(tree,"Files");
	tabsWidget->addTab(updates,"Updates");

	//Window
	setWindowTitle("Tubox User Interface - Tui");
	setCentralWidget(tabsWidget);
	addToolBar(Qt::BottomToolBarArea, toolBar);
	menuBar()->addMenu(fileMenu);
	menuBar()->addMenu(helpMenu);

	if (!QDBusConnection::sessionBus().isConnected()) {
		cerr << "Cannot connect to the D-Bus session bus.\n" <<
				"To start it, run:\n" <<
				"\teval `dbus-launch --auto-syntax`\n";
	}
	if (!QDBusConnection::sessionBus().registerService("com.tubox.Daemon.Comm")) {
		cerr << QDBusConnection::sessionBus().lastError().message().toStdString() << endl;
	}
	else {
		QDBusConnection::sessionBus().registerObject("/", this, QDBusConnection::ExportAllSlots);
	}
}

MainWindow::~MainWindow() {}

QString MainWindow::fileDownloaded(const QString& name) {
	updates->insertItem(0,"    File " + name + " downloaded");
	QLabel *label = new QLabel(updates);
	QPixmap pix("img/go-down.png");
	label->setPixmap(pix);
	updates->setItemWidget(updates->item(0), label);
	updateList();

	return "";
}

QString MainWindow::fileCreated(const QString& name) {
	updates->insertItem(0,"    File " + name + " created");
	QLabel *label = new QLabel(updates);
	QPixmap pix("img/document-new.png");
	label->setPixmap(pix);
	updates->setItemWidget(updates->item(0), label);
	updateList();

	return "";
}

QString MainWindow::fileUploaded(const QString& name) {
	updates->insertItem(0,"    File " + name + " uploaded");
	QLabel *label = new QLabel(updates);
	QPixmap pix("img/go-up.png");
	label->setPixmap(pix);
	updates->setItemWidget(updates->item(0), label);
	updateList();

	return "";
}

QString MainWindow::fileRemoved(const QString& name) {
	updates->insertItem(0,"    File " + name + " removed");
	QLabel *label = new QLabel(updates);
	QPixmap pix("img/edit-delete16.png");
	label->setPixmap(pix);
	updates->setItemWidget(updates->item(0), label);
	updateList();

	return "";
}

QString MainWindow::fileRenamed(const QString& oldName, const QString& newName) {
	updates->insertItem(0,"    File " + oldName + " renamed to " + newName);
	QLabel *label = new QLabel(updates);
	QPixmap pix("img/edit-rename16.png");
	label->setPixmap(pix);
	updates->setItemWidget(updates->item(0), label);
	updateList();

	return "";
}

QString MainWindow::folderCreated(const QString& name) {
	updates->insertItem(0,"    Folder " + name + " created");
	QLabel *label = new QLabel(updates);
	QPixmap pix("img/folder-new16.png");
	label->setPixmap(pix);
	updates->setItemWidget(updates->item(0), label);
	updateList();

	return "";
}

QString MainWindow::folderRenamed(const QString& oldName, const QString& newName) {
	updates->insertItem(0,"    Folder " + oldName + " renamed to " + newName);
	QLabel *label = new QLabel(updates);
	QPixmap pix("img/edit-rename16.png");
	label->setPixmap(pix);
	updates->setItemWidget(updates->item(0), label);
	updateList();

	return "";
}

void MainWindow::updateList() {
	QDirModel *model = new QDirModel(QStringList(), QDir::NoDotAndDotDot | QDir::AllEntries, QDir::Name);
	tree->setModel(model);
	tree->setAnimated(true);
	tree->setIndentation(20);
	tree->setSortingEnabled(true);
	tree->setRootIndex(model->index(path));
}

void MainWindow::disconnect() {
	//Communication with daemon

}

void MainWindow::copy() {
	QString entry, destination, origin, name;
	QModelIndex selected = tree->currentIndex();
	do {
		entry.prepend("/" + selected.data().toString());
		selected = selected.parent();
	} while(selected != QModelIndex());
	entry.replace(QRegExp("/{2,}"),"/");
	origin = entry.left(entry.lastIndexOf("/", -2) + 1);
	bool ok;
	destination = QInputDialog::getText(this,
																			"Destination Folder",
																			"Enter the copy destination",
																			QLineEdit::Normal,
																			"",
																			&ok);
	if(!ok)
		return;
	if(destination == "") {
		QMessageBox::critical(this,
													"Destination folder error",
													"You need to say to witch destination folder the file is going to be copied.");
		return;
	}
	destination = path + "/" + destination;
	destination.replace(QRegExp("/{2,}"),"/");
	QDir newDir(destination);
	if(!(newDir.exists())) {
		QMessageBox::critical(this,
													"Destination folder error",
													"This destination folder doesn't exist.");
		return;
	}
	if(newDir.exists(name)) {
		QMessageBox::critical(this,
													"Destination folder error",
													"This folder already contains an entry with this name.");
		return;
	}
	if(destination == origin) {
		QMessageBox::critical(this,
													"Destination folder error",
													"The destination folder is the same as the origin folder.");
		return;
	}
	//Communication with daemon
}

void MainWindow::move() {
	QString entry, destination, origin, name;
	QModelIndex selected = tree->currentIndex();
	do {
		entry.prepend("/" + selected.data().toString());
		selected = selected.parent();
	} while(selected != QModelIndex());
	entry.replace(QRegExp("/{2,}"),"/");
	origin = entry.left(entry.lastIndexOf("/", -2) + 1);
	name = entry.right(entry.length() - entry.lastIndexOf("/", -2) - 1);
	bool ok;
	destination = QInputDialog::getText(this,
																			"Destination Folder",
																			"Enter the move destination",
																			QLineEdit::Normal,
																			"",
																			&ok);
	if (!ok)
		return;
	if(destination == "") {
		QMessageBox::critical(this,
													"Destination folder error",
													"You need to say to witch destination folder the file is going to be moved.");
		return;
	}
	destination = path + "/" + destination;
	destination.replace(QRegExp("/{2,}"),"/");
	QDir newDir(destination);
	if(!(newDir.exists())) {
		QMessageBox::critical(this,
													"Destination folder error",
													"This destination folder doesn't exist.");
		return;
	}
	if(newDir.exists(name)) {
		QMessageBox::critical(this,
													"Destination folder error",
													"This folder already contains an entry with this name.");
		return;
	}
	if(destination == origin) {
		QMessageBox::critical(this,
													"Destination folder error",
													"The destination folder is the same as the origin folder.");
		return;
	}
	//Communication with daemon
}

void MainWindow::remove() {
	QString entry;
	QModelIndex selected = tree->currentIndex();
	do {
		entry.prepend("/" + selected.data().toString());
		selected = selected.parent();
	} while(selected != QModelIndex());

	QDBusInterface *iface;
	if (!QDBusConnection::sessionBus().isConnected()) {
		cerr << "Cannot connect to the D-Bus session bus." << endl;
		return;
	}
	iface = new QDBusInterface("com.tubox.Daemon.Ui", "/", "", QDBusConnection::sessionBus());
	if (!iface->isValid()) {
		delete iface;
		cerr << string("Cannot create a DBus Interface.") + QDBusConnection::sessionBus().lastError().message().toStdString() << endl;
		return;
	}
	QString message = "askDelete";
	QDBusReply<QString> reply = iface->call(message, entry.left(entry.lastIndexOf("/", -2) + 1), entry.right(entry.length() - entry.lastIndexOf("/", -2) - 1));
	if (!reply.isValid()) {
		 cerr << string("Could not call a valid slot.") << reply.error().message().toStdString() << " message: " << message.toStdString() << endl;
		 return;
	}
}

void MainWindow::rename() {
	QString entry, entryPath, newName;
	QModelIndex selected = tree->currentIndex();
	do {
		entry.prepend("/" + selected.data().toString());
		selected = selected.parent();
	} while(selected != QModelIndex());
	entry.replace(QRegExp("/{2,}"),"/");
	entryPath = entry.left(entry.lastIndexOf('/',-2) + 1);
	bool ok;
	newName = QInputDialog::getText(this,
																	"New Name",
																	"Enter the new name for the entry",
																	QLineEdit::Normal,
																	"",
																	&ok);
	if(!ok)
		return;
	if(newName == "") {
		QMessageBox::critical(this,
													"New name error",
													"You need to say the new name.");
		return;
	}
	if(newName.contains('/')) {
		QMessageBox::critical(this,
													"New name error",
													"You need to type a valid destination");
		return;
	}
	newName = entryPath + newName;
	if(QFileInfo(newName).exists()){
		QMessageBox::critical(this, "New name error",
													"Entry with this name already exists.");
	}
	//Communication with daemon
}

void MainWindow::createFolder() {
	QString destination;
	bool ok;
	destination = QInputDialog::getText(this,
																			"Destination Folder",
																			"Enter the move destination",
																			QLineEdit::Normal,
																			"",
																			&ok);
	if (!ok)
		return;
	if(destination == "") {
		QMessageBox::critical(this,
													"Destination folder error",
													"You need to say the name of the new folder.");
		return;
	}
	destination = path + "/" + destination;
	destination.replace(QRegExp("/{2,}"),"/");
	QDir newDir(destination);
	if(newDir.exists()) {
		QMessageBox::critical(this,
													"Destination folder error",
													"This folder already exists.");
		return;
	}
	//Communication with daemon
}

}
